<template>
  <el-select :size="size" filterable v-model="valueModel"
             :placeholder="placeholder" :clearable="clearable"
             @clear="clearChecked" @input="onInput"
             :popper-options="popper_options" :filter-method="filterMethod">

    <el-option style="display: none" :value="valueModel" :label="select_label"></el-option>

    <div style="max-height: 200px; min-height: 160px">
      <div class="sea-scroll-bar">
        <el-tree ref="treeRef" node-key="id" :data="tree"
                 default-expand-all :expand-on-click-node="false"
                 accordion @node-click="nodeClick"
                 :filter-node-method="filterNode">
          <template #default="{ node, data }">
            <span class="custom-tree-node">
              <i :class="data.icon"></i>{{ data.label }}
            </span>
          </template>
        </el-tree>
      </div>
    </div>
  </el-select>
</template>

<script setup lang="ts">
import {computed, ref, watch} from 'vue';
import Bamboo from "@/lang/bamboo";
import Layers from "@/lang/layers/index";
import TreeNode from "@/lang/bamboo/tree-node";
import {useFilterText, UseTree, useTree} from "@/widget/use/use-tree";
import {usePopperOptions} from "@/widget/use/use-popper-options";

/**
 * 下拉单选树形选择器
 *
 * element-plus 已经实现了这一功能，但是，直觉上认为应当保留这一代码；
 *
 * 树形组件会包含很复杂的逻辑，这一份代码仍有重要参考价值;
 *
 * 当前组件保留了个人设计习惯，与其它组件的使用方式相对统一。
 */
interface Props extends /* @vue-ignore */ UseTree{
    /** model-value */
    modelValue: string| boolean | number
    /** 组件大小 */
    size?: string
    /** 输入框的占位文字提示 */
    placeholder?: string

    /** 是否显示清除按钮 */
    clearable?: boolean

    /** 数据字典配置 */
    options?: TreeNode[]
    /** 异步查询参数 */
    where?: Record<string, any>
    /** 异步获取数结构数据 */
    provider?: (params: Record<string, any>) => Promise<TreeNode[]>
}

// 使用 withDefaults 设置默认值
const props = withDefaults(defineProps<Props>(), {
    size: 'default',
    placeholder: '',
    clearable: true
})

// 弹窗配置，没这玩意儿会报错
const popper_options = usePopperOptions();

// Emits
const emit = defineEmits(['update:modelValue', 'change']);

// 显示的文本
const label = ref('');
const select_label = ref('');

// 定义要触发的事件，用于更新 v-model 的值
const valueModel = computed({
    get() {
        return props.modelValue;
    },
    set(val) {
        emit('update:modelValue', val);
        emit('change', val);
    }
});

/**
 * 树节点数据发生变化重新匹配数据
 */
const onchange = (tree: TreeNode[]) =>{
    const val = valueModel.value;
    if (val == null || Layers.isEmpty(tree)) {
        select_label.value = '';
    } else {
        const node = Bamboo.getNodeById(tree, val);
        select_label.value = node ? node.label : val;
    }
}

// References
const treeRef = ref<InstanceType<typeof ElTree>>()

// 使用混合
const {tree, loading} = useTree(props, onchange);

// 使用过滤
const {filterText, filterNode, filterMethod} = useFilterText(treeRef);

/**
 * 值改变事件
 */
const onInput = (evt) => {
    if (evt instanceof InputEvent) {
        // console.log(evt);
    }
}

/**
 * 清除选中
 */
const clearChecked = () => {
    select_label.value = '';
    valueModel.value = '';
};

/**
 * 选中节点
 */
const nodeClick = (node) => {
    select_label.value = node.label;
    valueModel.value = node.id;
};

</script>

<style scoped>
/* Add your styles here */
</style>